package com.app.service.Impl;

import com.app.entity.po.HuibenCategory;
import com.app.entity.po.HuibenBook;
import com.app.entity.po.HuibenBookCollection;
import com.app.entity.po.BookPage;
import com.app.entity.po.HuibenReadingHistory;
import com.app.entity.po.HuibenCollect;
import com.app.entity.po.HuibenLike;
import com.app.entity.dto.ReadingRecordDTO;
import com.app.entity.po.HuibenComment;
import com.app.entity.po.HuibenFollow;
import com.app.entity.po.MemberUser;
import com.app.entity.dto.AddCommentDTO;
import com.app.vo.BookCommentVO;
import com.app.vo.AddCommentResponseVO;
import com.app.mapper.HuibenCategoryMapper;
import com.app.mapper.HuibenCategoryBooksMapper;
import com.app.mapper.HuibenBookCollectionMapper;
import com.app.mapper.HuibenBookCollectionBookMapper;
import com.app.mapper.HuibenBookMapper;
import com.app.mapper.HuibenBookPageMapper;
import com.app.mapper.HuibenReadingHistoryMapper;
import com.app.mapper.HuibenCollectMapper;
import com.app.mapper.HuibenLikeMapper;
import com.app.mapper.HuibenCommentMapper;
import com.app.mapper.HuibenFollowMapper;
import com.app.mapper.AppMemberUserMapper;
import com.app.service.IHuibenService;
import com.app.vo.CategoryVO;
import com.app.vo.BookTopicVO;
import com.app.vo.BookCollectionVO;
import com.app.vo.BookVO;
import com.app.vo.BookPageVO;
import com.app.vo.RecentBookVO;
import com.app.vo.BookInfoVO;
import com.app.vo.LikeResponseVO;
import com.app.vo.CollectResponseVO;
import com.app.vo.FollowResponseVO;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.util.object.BeanUtils.toBean;

@Service
@RequiredArgsConstructor
public class HuibenServiceImpl implements IHuibenService {

    // 静态常量：图片和音频的基础URL
    private static final String BASE_URL = "http://6a0fad0a.r8.vip.cpolar.cn/books/";
    

    private final HuibenCategoryMapper huibenCategoryMapper;
    private final HuibenCategoryBooksMapper categoryBooksMapper;
    private final HuibenBookCollectionMapper bookCollectionMapper;
    private final HuibenBookCollectionBookMapper bookCollectionBookMapper;
    private final HuibenBookMapper bookMapper;
    private final HuibenBookPageMapper bookPageMapper;
    private final HuibenReadingHistoryMapper readingHistoryMapper;
    private final HuibenCollectMapper collectMapper;
    private final HuibenLikeMapper likeMapper;
    private final HuibenCommentMapper commentMapper;
    private final HuibenFollowMapper followMapper;
    private final AppMemberUserMapper memberUserMapper;

    @Override
    public List<CategoryVO> getBookCategories(String lang) {
        List<HuibenCategory> list = huibenCategoryMapper.selectByLanguage(lang);
        return toBean(list, CategoryVO.class);
    }

    @Override
    public List<BookTopicVO> getBookList(Long categoryId) {
        // 1) 找分类，判定语言
        HuibenCategory category = huibenCategoryMapper.selectById(categoryId);
        if (category == null) {
            return Collections.emptyList();
        }
        String language = category.getLanguage();
        List<BookTopicVO> resultList;
        if ("en".equals(language) || "zh".equals(language)) {
            // 分类为绘本集：通过中间表查关联的 bookid（此处表示绘本集 id）
            List<Long> collectionIds = categoryBooksMapper.selectBookIdsByCategoryId(categoryId);
            if (collectionIds == null || collectionIds.isEmpty()) {
                return Collections.emptyList();
            }
            List<HuibenBookCollection> collections = bookCollectionMapper.selectByIds(collectionIds);
            resultList = toBean(collections, BookTopicVO.class);
        } else {
            // language = all，通过中间表查关联的 bookid（此处表示绘本 id）
            List<Long> bookIds = categoryBooksMapper.selectBookIdsByCategoryId(categoryId);
            if (bookIds == null || bookIds.isEmpty()) {
                return Collections.emptyList();
            }
            List<HuibenBook> books = bookMapper.selectByBookIds(bookIds);
            resultList = toBean(books, BookTopicVO.class);
        }
        // 拼接 coverUrl
        if (resultList != null) {
            for (BookTopicVO vo : resultList) {
                if (vo.getCoverUrl() != null && !vo.getCoverUrl().startsWith("http")) {
                    vo.setCoverUrl(BASE_URL + vo.getCoverUrl());
                }
            }
        }
        return resultList;
    }

    @Override
    public BookCollectionVO getBookCollectionDetail(Long collectionId) {
        // 1) 查询绘本集基本信息
        HuibenBookCollection collection = bookCollectionMapper.selectById(collectionId);
        if (collection == null) {
            return null;
        }
        // 2) 查询绘本集关联的绘本ID列表
        List<Long> bookIds = bookCollectionBookMapper.selectBookIdsByCollectionId(collectionId);
        if (bookIds == null || bookIds.isEmpty()) {
                    // 如果没有关联的绘本，返回空的绘本列表
        BookCollectionVO result = new BookCollectionVO();
        result.setId(collection.getId());
        result.setTitle(collection.getTitle());
        result.setBooks(Collections.emptyList());
        return result;
        }
        // 3) 查询绘本详细信息
        List<HuibenBook> books = bookMapper.selectByBookIds(bookIds);
        // 4) 转换为VO对象
        BookCollectionVO result = new BookCollectionVO();
        result.setId(collection.getId());
        result.setTitle(collection.getTitle());
        
        List<BookVO> bookVOs = toBean(books, BookVO.class);
        // 查询当前用户已读的绘本，标记状态
        try {
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            if (userId != null && bookVOs != null && !bookVOs.isEmpty()) {
                com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<HuibenReadingHistory> historyQw =
                        new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
                historyQw.eq("user_id", userId)
                        .in("book_id", bookIds);
                List<HuibenReadingHistory> histories = readingHistoryMapper.selectList(historyQw);
                Set<Long> readBookIds = histories == null ? Collections.emptySet() :
                        histories.stream().map(HuibenReadingHistory::getBookId).collect(Collectors.toSet());

                for (BookVO vo : bookVOs) {
                    if (vo.getCoverUrl() != null && !vo.getCoverUrl().startsWith("http")) {
                        vo.setCoverUrl(BASE_URL + vo.getCoverUrl());
                    }
                    if (readBookIds.contains(vo.getId())) {
                        vo.setStatus("已读");
                    }
                }
            } else if (bookVOs != null) {
                // 未登录也要拼接封面URL
                for (BookVO vo : bookVOs) {
                    if (vo.getCoverUrl() != null && !vo.getCoverUrl().startsWith("http")) {
                        vo.setCoverUrl(BASE_URL + vo.getCoverUrl());
                    }
                }
            }
        } catch (Exception ignore) {
            // 安全上下文异常时，至少保证封面URL被拼接
            if (bookVOs != null) {
                for (BookVO vo : bookVOs) {
                    if (vo.getCoverUrl() != null && !vo.getCoverUrl().startsWith("http")) {
                        vo.setCoverUrl(BASE_URL + vo.getCoverUrl());
                    }
                }
            }
        }
        result.setBooks(bookVOs);
        return result;
    }

    @Override
    public List<BookPageVO> getBookPages(Long bookId) {
        // 1) 根据绘本ID查询绘本页列表，按页码升序排序
        List<BookPage> bookPages = bookPageMapper.selectByBookIdOrderByPageNum(bookId);
        if (bookPages == null || bookPages.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 2) 转换为VO对象
        List<BookPageVO> bookPageVOs = toBean(bookPages, BookPageVO.class);
        
        // 3) 拼接图片和音频的完整URL
        for (int i = 0; i < bookPages.size(); i++) {
            BookPage bookPage = bookPages.get(i);
            BookPageVO bookPageVO = bookPageVOs.get(i);
            
            // 拼接图片URL
            if (bookPage.getImageUrl() != null && !bookPage.getImageUrl().trim().isEmpty()) {
                bookPageVO.setImageUrl(BASE_URL + bookPage.getImageUrl());
            }
            
            // 拼接音频URL（如果存在）
            if (bookPage.getAudioUrl() != null && !bookPage.getAudioUrl().trim().isEmpty()) {
                bookPageVO.setAudioUrl(BASE_URL + bookPage.getAudioUrl());
            }
        }
        
        return bookPageVOs;
    }

    @Override
    public Boolean saveReadingRecord(ReadingRecordDTO readingRecordDTO) {
        try {
            // 1) 从Spring Security上下文获取当前用户ID
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            if (userId == null) {
                throw new RuntimeException("用户未登录");
            }

            // 2) 解析时间字符串格式: "2025-08-15 14:40:49"
            // 使用DateTimeFormatter解析本地时间格式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime startTime = LocalDateTime.parse(readingRecordDTO.getStartTime(), formatter);
            LocalDateTime endTime = LocalDateTime.parse(readingRecordDTO.getEndTime(), formatter);

            // 3) 查询是否已存在该用户对该绘本的阅读记录
            com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<HuibenReadingHistory> queryWrapper = 
                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
            queryWrapper.eq("user_id", userId)
                       .eq("book_id", readingRecordDTO.getBookId());
            
            HuibenReadingHistory existingRecord = readingHistoryMapper.selectOne(queryWrapper);

            if (existingRecord != null) {
                // 4a) 如果存在记录，则更新阅读时长和结束时间
                existingRecord.setReadTime(readingRecordDTO.getReadTime());
                existingRecord.setEndTime(endTime);
                
                int updateResult = readingHistoryMapper.updateById(existingRecord);
                return updateResult > 0;
            } else {
                // 4b) 如果不存在记录，则新增
                HuibenReadingHistory readingHistory = new HuibenReadingHistory();
                readingHistory.setUserId(userId);
                readingHistory.setBookId(readingRecordDTO.getBookId());
                readingHistory.setStartTime(startTime);
                readingHistory.setReadTime(readingRecordDTO.getReadTime());
                readingHistory.setEndTime(endTime);

                int insertResult = readingHistoryMapper.insert(readingHistory);
                return insertResult > 0;
            }
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public List<RecentBookVO> getRecentBooks() {
        try {
            // 1) 从Spring Security上下文获取当前用户ID
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            if (userId == null) {
                throw new RuntimeException("用户未登录");
            }

            // 2) 计算时间范围：当前时间减去7天
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime sevenDaysAgo = now.minusDays(7);

            // 3) 查询该用户在最近7天内的阅读记录，按开始时间倒序排列
            com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<HuibenReadingHistory> queryWrapper = 
                new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<>();
            queryWrapper.eq("user_id", userId)
                       .between("start_time", sevenDaysAgo, now)
                       .orderByDesc("start_time");

            List<HuibenReadingHistory> readingHistories = readingHistoryMapper.selectList(queryWrapper);

            if (readingHistories == null || readingHistories.isEmpty()) {
                return Collections.emptyList();
            }

            // 4) 去重并限制数量：确保book_id不重复，最多返回6个
            List<Long> uniqueBookIds = readingHistories.stream()
                .map(HuibenReadingHistory::getBookId)
                .distinct()
                .limit(6)
                .collect(Collectors.toList());

            if (uniqueBookIds.isEmpty()) {
                return Collections.emptyList();
            }

            // 5) 根据book_id查询绘本详细信息
            List<HuibenBook> books = bookMapper.selectBatchIds(uniqueBookIds);

            if (books == null || books.isEmpty()) {
                return Collections.emptyList();
            }

            // 6) 转换为VO对象并拼接coverUrl
            List<RecentBookVO> result = toBean(books, RecentBookVO.class);
            for (RecentBookVO vo : result) {
                if (vo.getCoverUrl() != null && !vo.getCoverUrl().startsWith("http")) {
                    vo.setCoverUrl(BASE_URL + vo.getCoverUrl());
                }
            }

            return result;
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            return Collections.emptyList();
        }
    }

    @Override
    public BookInfoVO getBookInfo(Long bookId) {
        try {
            // 1) 根据绘本ID查询绘本基本信息
            HuibenBook book = bookMapper.selectById(bookId);
            if (book == null) {
                return null;
            }

            // 2) 转换为VO对象
            BookInfoVO bookInfoVO = new BookInfoVO();
            bookInfoVO.setId(book.getId());
            bookInfoVO.setTitle(book.getTitle());
            bookInfoVO.setTotalPage(book.getTotalpage());
            bookInfoVO.setInfo(book.getInfo());
            bookInfoVO.setLove(book.getLove());
            bookInfoVO.setCollect(book.getCollect());

            // 3) 处理封面URL
            if (book.getCoverUrl() != null && !book.getCoverUrl().startsWith("http")) {
                bookInfoVO.setCoverUrl(BASE_URL + book.getCoverUrl());
            } else {
                bookInfoVO.setCoverUrl(book.getCoverUrl());
            }

            // 4) 处理创建时间，转换为字符串格式
            if (book.getCreatedAt() != null) {
                bookInfoVO.setCreatedAt(book.getCreatedAt().toString());
            }

            // 5) 查询当前用户是否喜欢和收藏该绘本
            try {
                Long userId = SecurityFrameworkUtils.getLoginUserId();
                if (userId != null) {
                    // 查询是否喜欢
                    HuibenLike likeRecord = likeMapper.selectByUserIdAndBookId(userId, bookId);
                    bookInfoVO.setIsLiked(likeRecord != null);
                    
                    // 查询是否收藏
                    HuibenCollect collectRecord = collectMapper.selectByUserIdAndBookId(userId, bookId);
                    bookInfoVO.setIsCollected(collectRecord != null);
                } else {
                    // 未登录用户，设置为false
                    bookInfoVO.setIsLiked(false);
                    bookInfoVO.setIsCollected(false);
                }
            } catch (Exception ignore) {
                // 安全上下文异常时，设置为false
                bookInfoVO.setIsLiked(false);
                bookInfoVO.setIsCollected(false);
            }

            return bookInfoVO;
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public LikeResponseVO toggleBookLike(Long bookId) {
        try {
            // 1) 从Spring Security上下文获取当前用户ID
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            if (userId == null) {
                throw new RuntimeException("账号未登录");
            }

            // 2) 查询是否已存在该用户对该绘本的点赞记录
            HuibenLike existingLike = likeMapper.selectByUserIdAndBookId(userId, bookId);
            LikeResponseVO response = new LikeResponseVO();

            if (existingLike != null) {
                // 3a) 如果存在记录，则删除点赞记录
                int deleteResult = likeMapper.deleteById(existingLike.getId());
                if (deleteResult > 0) {
                    // 减少绘本点赞数量
                    bookMapper.decreaseLoveCount(bookId);
                    response.setIsLiked(false);
                } else {
                    throw new RuntimeException("取消点赞失败");
                }
            } else {
                // 3b) 如果不存在记录，则新增点赞记录
                HuibenLike newLike = new HuibenLike();
                newLike.setUserId(userId);
                newLike.setBookId(bookId);
                newLike.setCreatedAt(LocalDateTime.now());

                int insertResult = likeMapper.insert(newLike);
                if (insertResult > 0) {
                    // 增加绘本点赞数量
                    bookMapper.increaseLoveCount(bookId);
                    response.setIsLiked(true);
                } else {
                    throw new RuntimeException("点赞失败");
                }
            }

            // 4) 查询更新后的点赞数量
            HuibenBook book = bookMapper.selectById(bookId);
            response.setLoveCount(book != null ? book.getLove() : 0);

            return response;
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            throw new RuntimeException("点赞操作失败: " + e.getMessage());
        }
    }

    @Override
    public CollectResponseVO toggleBookCollect(Long bookId) {
        try {
            // 1) 从Spring Security上下文获取当前用户ID
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            if (userId == null) {
                throw new RuntimeException("账号未登录");
            }

            // 2) 查询是否已存在该用户对该绘本的收藏记录
            HuibenCollect existingCollect = collectMapper.selectByUserIdAndBookId(userId, bookId);
            CollectResponseVO response = new CollectResponseVO();

            if (existingCollect != null) {
                // 3a) 如果存在记录，则删除收藏记录
                int deleteResult = collectMapper.deleteById(existingCollect.getId());
                if (deleteResult > 0) {
                    // 减少绘本收藏数量
                    bookMapper.decreaseCollectCount(bookId);
                    response.setIsCollected(false);
                } else {
                    throw new RuntimeException("取消收藏失败");
                }
            } else {
                // 3b) 如果不存在记录，则新增收藏记录
                HuibenCollect newCollect = new HuibenCollect();
                newCollect.setUserId(userId);
                newCollect.setBookId(bookId);
                newCollect.setCreatedAt(LocalDateTime.now());

                int insertResult = collectMapper.insert(newCollect);
                if (insertResult > 0) {
                    // 增加绘本收藏数量
                    bookMapper.increaseCollectCount(bookId);
                    response.setIsCollected(true);
                } else {
                    throw new RuntimeException("收藏失败");
                }
            }

            // 4) 查询更新后的收藏数量
            HuibenBook book = bookMapper.selectById(bookId);
            response.setCollectCount(book != null ? book.getCollect() : 0);

            return response;
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            throw new RuntimeException("收藏操作失败: " + e.getMessage());
        }
    }

    @Override
    public List<BookCommentVO> getBookComments(Long bookId) {
        try {
            // 1) 根据绘本ID查询评论列表，按创建时间倒序排列
            List<HuibenComment> comments = commentMapper.selectByBookIdOrderByCreatedAt(bookId);
            if (comments == null || comments.isEmpty()) {
                return Collections.emptyList();
            }

            // 2) 获取当前登录用户ID
            final Long currentUserId = getCurrentUserIdSafely();

            // 3) 提取所有评论用户的ID
            List<Long> userIds = comments.stream()
                    .map(HuibenComment::getUserId)
                    .distinct()
                    .collect(Collectors.toList());

            // 4) 批量查询用户信息
            List<MemberUser> users = memberUserMapper.selectByUserIds(userIds);
            Map<Long, MemberUser> userMap = users.stream()
                    .collect(Collectors.toMap(MemberUser::getId, user -> user));

            // 5) 查询当前用户关注的用户列表
            Set<Long> followedUserIds = Collections.emptySet();
            if (currentUserId != null) {
                List<Long> targetUserIds = comments.stream()
                        .map(HuibenComment::getUserId)
                        .filter(userId -> !userId.equals(currentUserId))
                        .distinct()
                        .collect(Collectors.toList());

                if (!targetUserIds.isEmpty()) {
                    List<HuibenFollow> follows = new ArrayList<>();
                    for (Long targetUserId : targetUserIds) {
                        HuibenFollow follow = followMapper.selectByUserIdAndTargetUserId(currentUserId, targetUserId);
                        if (follow != null) {
                            follows.add(follow);
                        }
                    }
                    followedUserIds = follows.stream()
                            .map(HuibenFollow::getTargetUserId)
                            .collect(Collectors.toSet());
                }
            }

            // 6) 组装评论VO列表
            final Set<Long> finalFollowedUserIds = followedUserIds;
            List<BookCommentVO> result = comments.stream().map(comment -> {
                BookCommentVO vo = new BookCommentVO();
                vo.setId(comment.getId());
                vo.setUserId(comment.getUserId());
                vo.setBookId(comment.getBookId());
                vo.setCreatedAt(comment.getCreatedAt() != null ? comment.getCreatedAt().toString() : null);
                vo.setUserComment(comment.getUserComment());

                // 设置用户信息
                MemberUser user = userMap.get(comment.getUserId());
                if (user != null) {
                    vo.setUserAvatar(user.getAvatar());
                    vo.setUserName(user.getNickname() != null && !user.getNickname().trim().isEmpty() 
                            ? user.getNickname() : user.getName());
                }

                // 设置关注状态
                if (currentUserId != null && !comment.getUserId().equals(currentUserId)) {
                    vo.setFollow(finalFollowedUserIds.contains(comment.getUserId()));
                } else {
                    vo.setFollow(false);
                }

                return vo;
            }).collect(Collectors.toList());

            return result;
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            return Collections.emptyList();
        }
    }

    @Override
    public AddCommentResponseVO addBookComment(AddCommentDTO addCommentDTO) {
        try {
            // 1) 从Spring Security上下文获取当前用户ID
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            if (userId == null) {
                throw new RuntimeException("账号未登录");
            }

            // 2) 创建评论记录
            HuibenComment comment = new HuibenComment();
            comment.setUserId(userId);
            comment.setBookId(addCommentDTO.getBookId());
            comment.setUserComment(addCommentDTO.getComment());
            comment.setCreatedAt(LocalDateTime.now());

            // 3) 插入评论记录
            int insertResult = commentMapper.insert(comment);
            if (insertResult <= 0) {
                throw new RuntimeException("评论发布失败");
            }

            // 4) 构建响应对象
            AddCommentResponseVO response = new AddCommentResponseVO();
            response.setId(comment.getId());
            response.setUserComment(comment.getUserComment());

            return response;
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            throw new RuntimeException("评论发布失败: " + e.getMessage());
        }
    }

    /**
     * 安全获取当前用户ID，如果获取失败返回null
     */
    private Long getCurrentUserIdSafely() {
        try {
            return SecurityFrameworkUtils.getLoginUserId();
        } catch (Exception ignore) {
            return null;
        }
    }

    @Override
    public FollowResponseVO toggleUserFollow(Long targetUserId) {
        try {
            // 1) 从Spring Security上下文获取当前用户ID
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            if (userId == null) {
                throw new RuntimeException("账号未登录");
            }

            // 2) 不能关注自己
            if (userId.equals(targetUserId)) {
                throw new RuntimeException("不能关注自己");
            }

            // 3) 查询是否已存在该用户对该目标用户的关注记录
            HuibenFollow existingFollow = followMapper.selectByUserIdAndTargetUserId(userId, targetUserId);
            FollowResponseVO response = new FollowResponseVO();
            response.setUserId(targetUserId);

            if (existingFollow != null) {
                // 4a) 如果存在记录，则删除关注记录
                int deleteResult = followMapper.deleteById(existingFollow.getId());
                if (deleteResult > 0) {
                    response.setFollow(false);
                } else {
                    throw new RuntimeException("取消关注失败");
                }
            } else {
                // 4b) 如果不存在记录，则新增关注记录
                HuibenFollow newFollow = new HuibenFollow();
                newFollow.setUserId(userId);
                newFollow.setTargetUserId(targetUserId);
                newFollow.setCreatedAt(LocalDateTime.now());

                int insertResult = followMapper.insert(newFollow);
                if (insertResult > 0) {
                    response.setFollow(true);
                } else {
                    throw new RuntimeException("关注失败");
                }
            }

            return response;
        } catch (Exception e) {
            // 记录错误日志
            e.printStackTrace();
            throw new RuntimeException("关注操作失败: " + e.getMessage());
        }
    }
}

